【C语言内功心法】

您所在的位置:网站首页 cabletray weak翻译 【C语言内功心法】

【C语言内功心法】

2023-08-18 02:30| 来源: 网络整理| 查看: 265

大隐隐于市,小隐隐于野,深藏于人海,天下有道则见,无道则隐,君子藏器于身,待时而动。

-- 东方朔 +《周易》+ 《论语》

何为__weak?

__weak 用于修饰函数,赋予这个函数 弱 的属性。

在使用 STM32 的 hal 库的时候,我们常常可以看到很多库自带的函数有很多是使用 __weak 修饰的,比如:

image-20220911131759212

国内的知名操作系统 RT-Thread 也有大量使用 __weak 这个修饰符。

/* Compiler Related Definitions */ #ifdef __CC_ARM                         /* ARM Compiler */     #define RT_WEAK                     __weak #elif defined (__IAR_SYSTEMS_ICC__)     /* for IAR Compiler */     #define RT_WEAK                     __weak #elif defined (__GNUC__)                /* GNU GCC Compiler */     #define RT_WEAK                     __attribute__((weak)) #elif defined (__ADSPBLACKFIN__)        /* for VisualDSP++ Compiler */     #define RT_WEAK                     __attribute__((weak)) #elif defined (_MSC_VER)     #define RT_WEAK #elif defined (__TI_COMPILER_VERSION__)     #define RT_WEAK #else     #error not supported tool chain #endif

首先来看看,先看看单词的意思:

image-20220911111557334

整个单词的释义突出了一个 弱 字,虽然每个人努力修炼,都是为了变得更强,然后偶尔地示弱也是大智慧,那么 weak的弱能够在开发中提供怎样地帮助呢?

弱是相对的

首先 弱 是相对的,具体弱在哪里?又是和什么比较?

其实函数名称前面加上 __weak 修饰符,我们一般称这个函数为“弱函数”。

假如工程中存在了一个__weak 修饰符的函数,用户还可以在工程中重新定义一个与之同名的函数,最终编译器编译的时候,会选择没有__weak 修饰符的函数,如果用户没有重新定义新的函数,那么编译器就会执行 __weak 声明的函数,并且编译器不会报错。

既是弱肉强食,弱为何能生存?

一般来说,__weak 修饰符的函数是有软件供应商去定义的(比如 ST 提供的库函数),因为会使用到一些回调函数(比如中断回调函数等),所以需要定义该函数,才能在编译的时候不会报错。但是这些函数一般是开发者要使用,如果直接去软件供应商定义的函数里面实现功能,就会造成文件内容耦合,开发者切换平台或者工程时,做的工作量会更大。

所以软件供应商会用 __weak修饰实现函数,目的是保证编译能够正常通过,开发者要使用的时候,可以在自己的文件中再定义该函数,然后在该函数实现自己的功能,此时编译器会忽略 __weak弱化后的函数。当然如果你稍微懒了点,也可以不定义新的函数,用定义好的__weak修饰的函数实现自己的功能,编译器也照收不误。

还有一种情况是如果拿到的程序库的是软件包的格式(看不到源代码的那种),那你就得自己去定义这个同名函数去实现自己的功能。这个功能用处还挺大,笔者就遇到过要给客户提供功能模块代码,由于不能提供源码,只能提供软件包文件(一般格式为 .lib),但是又需要给客户提供调用的接口函数,我在软件包定义的话,客户用不了(因为看不到源码),我不定义的话,编译会报错,客户会怀疑你的工程是不是有问题。此时 __weak 真是应对这种问题的大救星,谁还能说它弱呢?

值得注意之处

从上文中的 RT-Thread 代码可以看到,__weak在不同平台有不同面孔,有些甚至没有,这是因为__weak函数修饰符并不是 C 标准的里面的东西,这意味着:

并不是所有的编译器都支持__weak这个特性,有些小众的编译器还真就不支持,所以使用前请查询相关编译器是否支持。

__weak在所有支持的编译器中面貌长的也一样,详情还是得查询相关编译器。长得不一样对于代码的移植性可是重大的打击,目前比较好的解决办法是:如前面 RT-Thread代码描述那样,用宏定义结合预编译的方式去给不同的 weak定义统一的名字,比如 RT_WEAK。

更多精彩内容,请点击 CSDN 博客地址: http://eureka1024.blog.csdn.net/。

更多精彩内容,请关注公众号《嵌入式小散修》。

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3